#include <iostream>
#include <memory>
#include <vector>
#include <string>
#include <string>
#include <fstream>
#include <streambuf>
#include <sstream>
#include <cstdlib>
#include <new>
#include <typeinfo>
#include <list>
#include <thread> // std::thread
#include <mutex>  // std::mutex

using namespace std;

// 参考: https://blog.csdn.net/misayaaaaa/article/details/53786215
// 参考: https://github.com/applenob/Cpp_Primer_Practice/blob/master/excersize/ch03.md
// chapter 3 字符串、向量和数组

// 1.
// using声明命名空间。注意的是头文件中不应该包含using声明，因为在引用头文件时，会将头文件中的内容拷贝到文件中来，如果头文件中包含了using声明，那么可能每一个头文件中都会包含using声明，可能会造成名字的冲突



// 2.
// 一次读入一行:
// string s;
// while (getline(cin, s))
// {
//     cout << s << endl;
// }

// 一次读入一个词:
// string s;
// while (cin >> s)
// {
//     cout << s << endl;
// }




// 3.
// 请说明string类的输入运算符和getline函数分别是如何处理空白字符的。

// 类似is >> s的读取：string对象会忽略开头的空白并从第一个真正的字符开始，直到遇见下一空白为止。
// 类似getline(is, s)的读取：string对象会从输入流中读取字符，直到遇见换行符为止
// 对于string类的输入函数，它会自动忽略开头的空白（空格、制表符、换行等等），从第一个真正的字符开始直到下一个空白。
// 对于getline()函数，它会保存字符串中的空白符，它读入数据，直到遇到换行符位置。


// 4.
// 对于字符串的比较：比较的是字符在字典中的顺序 ：b>a ，小写字母大于大写字母。
// 长度比较可以用size()函数


// 5.




// 6.

// 7.

// 8.
// 范围for语句更好，不直接操作索引，更简洁


// 9.
// 下面的程序有何作用？它合法吗？如果不合法？为什么？
string s;
cout << s[0] << endl;
// 解：
// 不合法。使用下标访问空字符串是非法的行为。



// 10.
// ispunct
// 判断一个字符串是否是标点
// 使用到了自带的函数： ispunct()判断字符是否为标点符号

// 11.
// 下面的范围for语句合法吗？如果合法，c的类型是什么？

// const string s = "Keep out!";
// for(auto &c : s)
// { /* ... */ }

// 要根据for循环中的代码来看是否合法，c是string 对象中字符的引用，s是常量。
// 因此如果for循环中的代码重新给c赋值就会非法，如果不改变c的值，那么合法
// C的类型是const char&



// 12.

vector<vector<int>> ivec;         // 在C++11当中合法
// vector<string> svec = ivec;       // 不合法，类型不一样
vector<string> svec(10, "null");  // 合法




// 13.
// 下列的vector对象各包含多少个元素？这些元素的值分别是多少？

vector<int> v1;         // size:0,  no values.
vector<int> v2(10);     // size:10, value:0
vector<int> v3(10, 42); // size:10, value:42
vector<int> v4{ 10 };     // size:1,  value:10
vector<int> v5{ 10, 42 }; // size:2,  value:10, 42
vector<string> v6{ 10 };  // size:10, value:""
vector<string> v7{ 10, "hi" };  // size:10, value:"hi"



// 14.



// 15.



// 16.




// 17.
// 可以使用C++中的toupper()函数快速转化为大写




// 18.
下面的程序合法吗？如果不合法，你准备如何修改？

vector<int> ivec;
ivec[0] = 42;
解：

不合法。应改为：

ivec.push_back(42);



// 19.
// 如果想定义一个含有10个元素的vector对象，所有元素的值都是42，请例举三种不同的实现方法，哪种方式更好呢？
// 如下三种：

// vector<int> ivec1(10, 42);
// vector<int> ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
// vector<int> ivec3;
// for (int i = 0; i < 10; ++i)
// 	ivec3.push_back(42);
// 第一种方式最好




// 20.




// 21.
// begin() 和 end() 位于iteartor; const_iterator end();
// front() 和 back()位于vector list deque; const_reference back();
begin函数：
函数原型:
iterator begin();
const_iterator begin();
功能：
返回一个当前vector容器中起始元素的迭代器。

end函数：
函数原型：
iterator end();
const_iterator end();
功能：
返回一个当前vector容器中末尾元素的迭代器。

front函数：
函数原型：
reference front();
const_reference front();
功能：
返回当前vector容器中起始元素的引用。

back函数：
函数原型：
reference back();
const_reference back();
功能：
返回当前vector容器中末尾元素的引用



// 22.


// 23.



// 24.



// 25.




// 26.
// 二分搜索程序中，为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ?
// 因为end指的是最后一个元素的后一个位置！！！（vectoer迭代器的性质要记清楚啦）




// 27.

// 假设txt_size是一个无参函数，它的返回值是int。请回答下列哪个定义是非法的，为什么？

// unsigned buf_size = 1024;
// (a) int ia[buf_size];
// (b) int ia[4 * 7 - 14];
// (c) int ia[txt_size()];
// (d) char st[11] = "fundamental";
// 解：

// (a) 非法。维度必须是一个常量表达式。
// (b) 合法。
// (c) 非法。txt_size() 的值必须要到运行时才能得到。
// (d) 非法。数组的大小应该是12。



// 理解复杂数组的声明(难点)
// 不可以将数组的内容拷贝给其他数组当作初始值，也不能用数组为其他数组赋值。

// int  a[3] = {0,1,3};
// int a1[]  = a;  //错误
// a2 = a; //错误

// 复杂数组声明的理解

// int *a[10];  //a数组含有10个指针整形
// int &a[10];  //错误，不存在引用的数组
// int (*a)[10]; //a是一个指针，指向一个含有10个整数的数组
// int (&a)[10]; //a是一个引用，引用一个含有10个整数的数组
// int *(&a)[10]; // a是数组的引用，数组含有十个指针

// 理解方法：从数组的名字开始，由内向外顺序读取，先左后右，左边为类型。



// 28.
// string sa[10];
// int ia[10];
// int main() {
// 	string sa2[10];
// 	int ia2[10];
// }
// string不是内置的数据类型，int是
// sa数组为空。
// ia数组含有10个整数，皆为0。
// sa2数组为空。
// ia2数组含有10个整数，在函数体内，值不确定
// 数组的元素会被默认初始化。 sa的元素值全部为空字符串，ia 的元素值全部为0。 sa2的元素值全部为空字符串，ia2的元素值全部未定义



// 29.
// 相比于vector 来说，数组有哪些缺点，请例举一些。

// 解：

// 数组的大小是确定的。
// 不能随意增加元素。
// 不允许拷贝和赋值




// 30.
指出下面代码中的索引错误。

constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
	ia[ix] = ix;
解：

当ix增长到 10 的时候，ia[ix]的下标越界




// 31.



// 32.



// 33.



// 34.
// 假定p1 和 p2 都指向同一个数组中的元素，则下面程序的功能是什么？什么情况下该程序是非法的？
// p1 += p2 - p1;

// 将 p1 移动到 p2 的位置。任何情况下都合法
// p1和p2是指针，相减为其地址相减，因为指向的是同一元素，地址相同，因次p1地址不变。
// 只要p1和p2合法，这个语句就是合法的




// 35.



// 36.



// 37.
下面的程序是何含义，程序的输出结果是什么？

const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp) {
    cout << *cp << endl;
    ++cp;
}
解：

会将ca 字符数组中的元素打印出来。但是因为没有空字符的存在，程序不会退出循环
输出：hello


// 38.
// 指针指代的是对象的地址，相加是地址相加，难以区分到底什么意义




// 39.



// 40.
// strcpy(a,b); 将b拷贝给a
// strcat(c,d); 将d加于c后




// 41.








int main()
{
    //   string s;
    //   cout<<s[0]<<endl;

    const string s = "Keep out!";
    for (auto &c : s)
    {
    }

    vector<string> svec(10, "null");

    printf("hello c++ \n");
}